package com.jweb.plugins.rpc.core;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URLEncoder;
import java.util.UUID;

import com.jweb.framework.AppConstant;
import com.jweb.framework.core.CharSet;
import com.jweb.plugins.rpc.Constant;
import com.jweb.plugins.rpc.annotation.RpcConsumer;
import com.jweb.plugins.rpc.bean.RpcRequest;
import com.jweb.plugins.rpc.bean.RpcResponse;
import com.jweb.plugins.rpc.bean.ZNode;
import com.jweb.plugins.rpc.impl.AgreementFactory;

/**
 * 客户端代理
 * 
 * @author Yuanqy
 *
 */
public class RpcProxy {

	private ZNode znode;

	@SuppressWarnings("unchecked")
	public <T> T create(final RpcConsumer rc, final Class<?> interfaceClass) throws Exception {
		// --创建消费节点
		final ZNode cliNode = new ZNode(AppConstant.CONFIG.LocalIP.getValue(), 0, 0, 0, rc.version(), rc.remark(), rc.serviceType());
		String path = Constant.ZK_REGISTRY_PATH + "/" + interfaceClass.getName() + "/" + Constant.CONSUMERS + "/"
				+ URLEncoder.encode(cliNode.toString(), CharSet.Default);
		ZkFactory.createPathLine(path);
		// --创建代理类
		return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] { interfaceClass }, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				RpcRequest request = new RpcRequest(); // 创建并初始化 RPC 请求
				request.setRequestId(UUID.randomUUID().toString());
				request.setClassName(method.getDeclaringClass().getName());
				request.setMethodName(method.getName());
				request.setParameterTypes(method.getParameterTypes());
				request.setParameters(args);
				request.setServiceTypeName(rc.serviceType().getName());
				znode = ZkFactory.discover(cliNode); // 发现服务
				// 通过 RPC 客户端发送 RPC
				RpcResponse response = AgreementFactory.startClient(request, znode.getHost(), znode.getPort(), znode.getServiceType());
				if (response.isError()) {
					throw response.getError();
				} else {
					return response.getResult();
				}
			}
		});
	}
}